﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Diagnostics;
using log4net;

namespace SharedGenomics.Core
{
    public class Log4NetLogger : ILogger
    {
        public void Log(LogEntry entry)
        {
            entry.ThrowIfNull("entry");

            ILog log = this.GetLog(entry.LogType ?? typeof(Log4NetLogger));
            this.WriteLogEntry(entry, log);
        }

        protected virtual ILog GetLog(Type logType)
        {
            Debug.Assert(logType != null);
            return LogManager.GetLogger(logType);
        }

        private void WriteLogEntry(LogEntry entry, ILog log)
        {
            Debug.Assert(entry != null);
            Debug.Assert(log != null);

            try
            {
                switch (entry.Priority)
                {
                    case MessagePriority.Fatal:
                        this.LogFatal(log, entry.Message, entry.Exception);
                        break;

                    case MessagePriority.Error:
                        this.LogError(log, entry.Message, entry.Exception);
                        break;

                    case MessagePriority.Warning:
                        this.LogWarning(log, entry.Message, entry.Exception);
                        break;

                    case MessagePriority.Debug:
                        this.LogDebug(log, entry.Message, entry.Exception);
                        break;

                    default:    //MessagePriority.Information
                        this.LogInformation(log, entry.Message, entry.Exception);
                        break;
                }
            }
            catch (Exception)
            {
                if (entry.ThrowOnLogFailure)
                    throw;
            }
        }

        private void LogFatal(ILog log, string message, Exception ex)
        {
            if (log.IsFatalEnabled)
            {
                if (ex == null)
                    log.Fatal(message);
                else
                    log.Fatal(message, ex);
            }
        }

        private void LogError(ILog log, string message, Exception ex)
        {
            if (log.IsErrorEnabled)
            {
                if (ex == null)
                    log.Error(message);
                else
                    log.Error(message, ex);
            }
        }

        private void LogWarning(ILog log, string message, Exception ex)
        {
            if (log.IsWarnEnabled)
            {
                if (ex == null)
                    log.Warn(message);
                else
                    log.Warn(message, ex);
            }
        }

        private void LogDebug(ILog log, string message, Exception ex)
        {
            if (log.IsDebugEnabled)
            {
                if (ex == null)
                    log.Debug(message);
                else
                    log.Debug(message, ex);
            }
        }

        private void LogInformation(ILog log, string message, Exception ex)
        {
            if (log.IsInfoEnabled)
            {
                if (ex == null)
                    log.Info(message);
                else
                    log.Info(message, ex);
            }
        }
    }
}
